#include<iostream>
#include <opencv4/opencv2/opencv.hpp>
#include <opencv4/opencv2/xfeatures2d.hpp>

using namespace std;
using namespace cv;
class dynamic
{
public:
    dynamic(int port):cap(port){
        cap.set(CAP_PROP_FRAME_WIDTH,this->cameraWidth);
	    cap.set(CAP_PROP_FRAME_HEIGHT,this->cameraHeigh);
        this->pBgModel->setHistory(1);
        this->pBgModel->setVarThreshold(10);
        this->pBgModel->setDetectShadows(false);
    };
    ~dynamic(){cap.release();};
    void setWidthAndHeigh(int width,int heigh){
        this->cameraWidth=width;
        this->cameraHeigh=heigh;
        cap.set(CAP_PROP_FRAME_WIDTH,this->cameraWidth);
        cap.set(CAP_PROP_FRAME_HEIGHT,this->cameraHeigh);
    }
    void discren(bool k){
        this->cap>>this->display;
        if(k){
            scan();
        }
        imshow("dynamic_display", this->display);
        waitKey(5);
    }
private:
    int cameraWidth=640;
    int cameraHeigh=480;
    VideoCapture cap;
    Mat display;
    Ptr<BackgroundSubtractorMOG2> pBgModel = createBackgroundSubtractorMOG2();
    int labelTargets(Mat& mask, int thresh);
    void scan();
    
};

int dynamic::labelTargets(Mat& mask, int thresh){
    //以下是图像分割
    Mat seg = mask.clone();
    vector<vector<Point>> cnts;
    findContours(seg, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    //以下进行筛选
    float area;
    Rect rect;
    int count = 0;
    string strCount;
    for (int i = cnts.size() - 1; i >= 0; i--)
    {
        vector<Point> c = cnts[i];
        area = contourArea(c);
        if (area < thresh)
            continue;
        count++;
        //包围特征点的矩形框的坐标和长宽信息
        rect = boundingRect(c);
        //输出矩形框的坐标和面积
        // cout << "位置：（" << rect.x << "，" << rect.y << "）面积：" << rect.width * rect.height << endl;
        //在原图上画出矩形框
        rectangle(this->display, rect, Scalar(0, 0, 0xff), 1);

        stringstream ss;
        ss << count;
        ss >> strCount;
        putText(this->display, strCount, Point(rect.x, rect.y), 1, 0.5, Scalar(0, 0xff, 0));
    }
    return count;
}

void dynamic::scan(){
    Mat source, foreGround, backGround, fgMask;
    this->cap >> this->display;
    // resize(source, this->display, Size(source.cols / 2, source.rows / 2), INTER_LINEAR);
    
    if (foreGround.empty())
        foreGround.create(this->display.size(), this->display.type());
    
    //背景更新
    this->pBgModel->apply(this->display, fgMask);

    //图像处理
    GaussianBlur(fgMask, fgMask, Size(5, 5), 0);
    threshold(fgMask, fgMask, 30, 255, THRESH_BINARY);

    foreGround = Scalar::all(0);
    //display和fgMask重叠以后把fgMask像素值为0对应display中的点变为透明，而保留其他点
    this->display.copyTo(foreGround, fgMask);
    labelTargets(fgMask,150);
}